package tt.dz.order.service;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import tt.dz.order.annotation.OrderLogAnnotation;
import tt.dz.order.dao.SysApplicationContextAware;
import tt.dz.order.exception.BusinessException;
import tt.dz.order.exception.ParamNotFoundInSystemException;
import tt.dz.order.pojo.*;
import tt.dz.order.service.drools.ActivityRuleService;
import tt.dz.order.service.rpc.client.MsRpcClient;
import tt.dz.order.util.AliPayUtil;
import tt.dz.order.util.AmountUtil;
import tt.dz.order.util.HttpUtils;
import tt.dz.order.util.OrderAppConfig;
import tt.dz.order.util.OrderConstant;
import tt.dz.order.util.OrderConstant.AdvancePaymentStage;
import tt.dz.order.util.OrderConstant.BizSystemCode;
import tt.dz.order.util.OrderConstant.BizType;
import tt.dz.order.util.OrderConstant.CardType;
import tt.dz.order.util.OrderConstant.MerchantOperationMode;
import tt.dz.order.util.OrderConstant.OrderPayChannelCode;
import tt.dz.order.util.OrderConstant.OrderPayWay;
import tt.dz.order.util.OrderConstant.OrderServiceEnum;
import tt.dz.order.util.OrderConstant.OrderStatus;
import tt.dz.order.util.OrderConstant.OrderType;
import tt.dz.order.util.OrderConstant.UserType;
import tt.dz.order.util.UUIDUtil;
import tt.dz.order.util.WeiXinPayUtilBase;
import tt.dz.order.util.XmlUtil;
import tt.dz.order.util.YouBeiPayUtil;
import tt.dz.order.util.thirdrecord.ThirdRecordQuery;
import tt.dz.order.util.thirdrecord.ThirdRecordQueryFactory;
import tt.dz.order.vo.AdvanceOrder;
import tt.dz.order.vo.AdvanceOrderItem;
import tt.dz.order.vo.CreatedOrderVO;
import tt.dz.order.vo.CreatedOrderVO.ServicePriceVO;
import tt.dz.order.vo.DivideInfo;
import tt.dz.order.vo.Order2WeiXinOrderRequestVo;
import tt.dz.order.vo.Order2WeiXinOrderResponseVo;
import tt.dz.order.vo.OrderBaseData;
import tt.dz.order.vo.OrderHistoryQueryVO;
import tt.dz.order.vo.OrderHistoryQueryVO.OrderHistoryQueryParamVO;
import tt.dz.order.vo.OrderHistoryQueryVO.OrderHistoryQueryRetVO;
import tt.dz.order.vo.OrderHistoryQueryVO.OrderItemHistoryQueryRetVO;
import tt.dz.order.vo.OrderInfoVo;
import tt.dz.order.vo.QueryOrderStatusVo;
import tt.dz.order.vo.RechargeOnlineAccount;
import tt.dz.order.vo.RetVO;
import tt.dz.order.vo.ThdPayWayRecord;
import tt.dz.order.vo.UserPayInfoVO;
import tt.dz.order.vo.WhiteListInfo;

/**
 * @author zhoutian
 * @Title 订单系统服务类
 * @date 2015-11-17
 */
@Service
public class OrderService {
    private static Logger log = LoggerFactory.getLogger(OrderService.class);
    private static String SUCCESS = "SUCCESS";

    @Autowired
    private ActivityRuleService activityRuleService;

    public OrderService() {
    }

    /**
     * 根据订单号查询订单信息
     *
     * @param orderNo 订单号
     * @return 订单信息
     */
    public OrderInfo getOrderByNo(String orderNo) {
        return OrderInfo.getById(orderNo);
    }

    /**
     * 服务价格查询
     *
     * @param orderBaseDatas
     * @return
     * @throws BusinessException
     */
    public List<ServicePriceVO> servicePriceQuery(List<OrderBaseData> orderBaseDatas) throws BusinessException {
        log.info("服务价格查询service层, orderBaseDatas:", orderBaseDatas);
        List<ServicePriceVO> servicePriceVOList = new ArrayList<ServicePriceVO>();
        if (orderBaseDatas != null && orderBaseDatas.size() > 0) {
            for (OrderBaseData orderBaseData : orderBaseDatas) {
                String cardType = orderBaseData.getCardType();
                String cardNo = orderBaseData.getCardNo();
                UserInfo user = UserInfo.getUserInfoBy(cardType, cardNo);
                if (user == null) {
                    throw new ParamNotFoundInSystemException("通过卡类型和卡号无法找到关联的用户");
                }
                orderBaseData.setUserId(user.getUserId());
                orderBaseData.setUserType(user.getUserType().toString());
                ProviderService providerService = ProviderService.getProviderServiceBy(orderBaseData.getServiceNo(),
                        orderBaseData.getServiceProviderCode());
                orderBaseData.setIsCost(providerService.getIsCost());
                // 服务的原始单价
                BigDecimal unitPrice = orderBaseData.getUnitPrice();
                // 服务的原始总价
                BigDecimal totalPrice = orderBaseData.getTotalPrice();
                // 获取白名单打折信息
                WhiteListInfo whiteListInfo = orderBaseData.getWhiteListInfo();
                if (whiteListInfo != null) {
                    BigDecimal disCount = whiteListInfo.getDiscount();
                    if (unitPrice != null && disCount != null) {
                        unitPrice = AmountUtil.multiply(unitPrice, disCount);
                    }
                    if (unitPrice != null && totalPrice != null) {
                        totalPrice = AmountUtil.multiply(totalPrice, disCount);
                    }
                }
                orderBaseData.setUnitPrice(unitPrice);
                orderBaseData.setTotalPrice(totalPrice);
            }
            // 使用规则引擎进行计算
            List<OrderItem> orderItems = activityRuleService.caculate(orderBaseDatas);
            for (OrderItem orderItem : orderItems) {
                // 将计算得到的OrderItem对象的部分属性放入ServicePriceVO中作为查询结果返回
                ServicePriceVO servicePriceVO = new ServicePriceVO();
                servicePriceVO.setServiceNo(orderItem.getServiceNo());
                OrderServiceInfo serviceInfo = OrderServiceInfo.getById(orderItem.getServiceNo());
                servicePriceVO.setServiceName(serviceInfo.getName());
                servicePriceVO.setBuyNum(orderItem.getBuyNum());
                servicePriceVO.setOriginalPrice(orderItem.getTotalPrice());
                servicePriceVO.setRealPrice(orderItem.getRealTotalPrice());
                servicePriceVOList.add(servicePriceVO);
            }
        }
        return servicePriceVOList;
    }

    /**
     * 通过询价项vo集合，包装订单总体询价vo结构
     *
     * @param vos
     * @return
     */
    public CreatedOrderVO wrapQueryOrderPriceVo(List<ServicePriceVO> vos) {
        CreatedOrderVO vo = new CreatedOrderVO();
        if (vos == null || vos.isEmpty()) {
            return vo;
        }
        String mainServiceNo = "";
        String mainServiceName = "";
        BigDecimal total = new BigDecimal(0);
        BigDecimal sub;
        for (ServicePriceVO servicePriceVO : vos) {
            if (StringUtils.isEmpty(mainServiceNo)) {
                String serviceNo = servicePriceVO.getServiceNo();
                OrderServiceInfo serviceInfo = OrderServiceInfo.getById(serviceNo);
                if (serviceInfo != null) {
                    mainServiceNo = serviceInfo.getParentNo();
                    mainServiceName = serviceInfo.getParentName();
                }
            }
            sub = servicePriceVO.getRealPrice();
            total = AmountUtil.add(total, sub);
        }
        vo.setMainServiceName(mainServiceName);
        vo.setMainServiceNo(mainServiceNo);
        vo.setOrderItemVOList(vos);
        vo.setTotalFee(total);
        return vo;
    }

    /**
     * 下单请求处理方法
     *
     * @param orderBaseDatas
     * @return
     * @throws BusinessException
     */
    @OrderLogAnnotation(bizCode = "createOrder", bizName = "下单", bizType = BizType.BUSINESS)
    public CreatedOrderVO createOrder(List<OrderBaseData> orderBaseDatas) throws BusinessException {
        log.info("下单请求service层, orderBaseDatas:", orderBaseDatas);
        CreatedOrderVO createdOrderVO = new CreatedOrderVO();
        OrderType orderType = OrderType.AFTER_PAYMENT;
        List<ServicePriceVO> servicePriceVOList = new ArrayList<ServicePriceVO>();
        if (orderBaseDatas != null && !orderBaseDatas.isEmpty()) {
            OrderBaseData orderBaseData0 = orderBaseDatas.get(0);
            // 当前第一个存在订单支付状态，则进行当前的状态校验
            OrderStatus status = OrderStatus.unPay;
            Integer payType = orderBaseData0.getPayType();
            int payStatus = status.value();
            if (orderBaseData0.getPayStatus() != null) {
                payStatus = orderBaseData0.getPayStatus();
                status = OrderStatus.getStatusByValue(payStatus);
                if (status == null) {
                    throw new BusinessException("当前订单状态不为空，但当前的支付状态传值未非法值");
                }
                payStatus = status.value();
            }
            // 支付类型
            OrderPayWay payWay = null;
            if (status == OrderStatus.payedDone) {
                // 当前若是已经支付，则进行当前的订单支付类型校验
                // 获取支付类型
                payWay = OrderPayWay.get(payType);
                if (payWay == null) {
                    throw new BusinessException("支付为已支付但支付类别为空");
                }
            }
            OrderInfo orderInfo = new OrderInfo();
            String cardType = orderBaseData0.getCardType();
            String cardNo = orderBaseData0.getCardNo();
            UserInfo user = UserInfo.getUserInfoBy(cardType, cardNo);
            if (user == null && !cardType.equals(CardType.OFFLINE_CARD.value())) {
                throw new ParamNotFoundInSystemException("通过卡类型和卡号无法找到关联的用户");
            }
            if (user != null) {
                orderBaseData0.setUserId(user.getUserId());
                orderBaseData0.setUserType(user.getUserType().toString());
            } else {
                orderBaseData0.setUserType(String.valueOf(UserType.offline_customer.value()));
            }
            String serviceNo = orderBaseData0.getServiceNo();
            OrderServiceInfo serviceInfo = OrderServiceInfo.getById(serviceNo);
            OrderServiceInfo mainServiceInfo = OrderServiceInfo.getById(serviceInfo.getParentNo());
            String appId = orderBaseData0.getAppId();
            orderInfo.setUserId(orderBaseData0.getUserId());
            orderInfo.setOrderType(orderType.value());
            orderInfo.setUserType(orderBaseData0.getUserType());
            orderInfo.setCardNo(orderBaseData0.getCardNo());
            orderInfo.setCardType(orderBaseData0.getCardType());
            orderInfo.setPayerBalance(orderBaseData0.getPayerBalance());
            orderInfo.setAppId(appId);
            // 订单的主服务编号
            orderInfo.setServiceNo(mainServiceInfo.getServiceNo());
            // 生成订单号
            orderInfo.setOrderNo(new StringBuilder(orderBaseData0.getUserType()).append(appId)
                    .append(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());
            // orderInfo.setRelatedOrderNo(orderInfo.getOrderNo());
            createdOrderVO.setOrderNo(orderInfo.getOrderNo());
            createdOrderVO.setMainServiceName(mainServiceInfo.getName());
            for (OrderBaseData orderBaseData : orderBaseDatas) {
                orderBaseData.setUserId(orderInfo.getUserId());
                orderBaseData.setUserType(orderInfo.getUserType());
                ProviderService providerService = ProviderService.getProviderServiceBy(orderBaseData.getServiceNo(),
                        orderBaseData.getServiceProviderCode());
                if (providerService == null) {
                    throw new ParamNotFoundInSystemException("通过serviceNo：" + orderBaseData.getServiceNo()
                            + "和serviceProviderCode：" + orderBaseData.getServiceProviderCode() + "无法找到服务与服务提供商的关联关系");
                }
                orderBaseData.setIsCost(providerService.getIsCost());
                orderBaseData.setUnitNo(providerService.getUnitNo());
                // 服务的原始单价
                BigDecimal unitPrice = orderBaseData.getUnitPrice();
                // 获取白名单打折信息
                WhiteListInfo whiteListInfo = orderBaseData.getWhiteListInfo();
                if (unitPrice != null && whiteListInfo != null) {
                    BigDecimal disCount = whiteListInfo.getDiscount();
                    if (disCount != null) {
                        unitPrice = AmountUtil.multiply(unitPrice, disCount);
                    }
                }
                orderBaseData.setUnitPrice(unitPrice);
            }
            // 使用规则引擎进行计算
            List<OrderItem> orderItems = activityRuleService.caculate(orderBaseDatas);
            for (OrderItem orderItem : orderItems) {
                OrderBaseData orderBaseData = orderItem.getOrderBaseData();
                OrderServiceInfo orderServiceInfo = OrderServiceInfo.getById(orderBaseData.getServiceNo());
                orderItem.setOrderNo(orderInfo.getOrderNo());
                orderItem.setIsCost(orderBaseData.getIsCost());
                orderItem.setItemId(DigestUtils.md5Hex(orderInfo.getOrderNo() + orderItem.getServiceNo()
                        + orderItem.getServiceProvider() + System.nanoTime()));
                orderItem.save();
                // 获取分润信息并计算
                DivideInfo divideInfo = orderBaseData.getDivideInfo();
                if (divideInfo != null) {
                    String merchantCodeStr = divideInfo.getMerchantCodes();
                    String[] merchantCodes = merchantCodeStr.split(",");
                    String ratioStr = divideInfo.getRatios();
                    String[] ratios = ratioStr.split(",");
                    String minAmountStr = divideInfo.getMinAmount();
                    // 保底金额（以逗号分隔）(传空值，则表明每一个保定金额都为0，反之将每个分润商的保底金额传递过来)
                    boolean hasMinAmount = !StringUtils.isEmpty(minAmountStr);
                    String[] minAmounts = null;
                    if (hasMinAmount) {
                        // 若有传递任何分润商的信息的时候
                        minAmounts = minAmountStr.split(",");
                        if (merchantCodes.length != minAmounts.length) {
                            throw new BusinessException("分润计算时获取传过来的merchantCode与保底金额信息个数不一致");
                        }
                    }
                    BigDecimal dividedSum = new BigDecimal("0.00");
                    String curMinAmountStr = "";
                    for (int i = 0; i < merchantCodes.length; i++) {
                        // 初始化保底金额
                        // 传过来中存在保底金额的时候 就从数组之中获取，反之没有传过来保底金额的时候，默认为0
                        curMinAmountStr = hasMinAmount ? minAmounts[i] : "0.00";
                        String merchantCode = merchantCodes[i];
                        Merchant merchant = Merchant.getById(merchantCode);
                        if (merchant == null) {
                            throw new BusinessException("分润计算时通过merchantCode：" + merchantCode + "无法找到合作商");
                        }
                        if (merchant.getIsSelf() == MerchantOperationMode.principal.value()) {
                            // 如果分润方是电桩自营的
                            orderInfo.setRealReceiver(merchantCode);
                        }
                        BigDecimal ratio = new BigDecimal(ratios[i]);
                        BigDecimal minAmount = new BigDecimal(curMinAmountStr);
                        BigDecimal splitedPrice = AmountUtil.multiply(orderItem.getRealTotalPrice(), ratio);
                        if (i == merchantCodes.length - 1) {
                            splitedPrice = AmountUtil.sub(orderItem.getRealTotalPrice(), dividedSum);
                        }
                        OrderItemDividedDetail orderItemDividedDetail = new OrderItemDividedDetail(orderItem,
                                merchantCode, ratio, minAmount, splitedPrice);
                        dividedSum = AmountUtil.add(dividedSum, splitedPrice);
                        orderItemDividedDetail.save();
                    }
                } else {
                    OrderItemDividedDetail orderItemDividedDetail = new OrderItemDividedDetail(orderItem);
                    orderItemDividedDetail.save();
                    String serviceProviderCode = orderItem.getServiceProvider();
                    Merchant merchant = Merchant.getById(serviceProviderCode);
                    if (merchant == null) {
                        throw new BusinessException("通过serviceProviderCode：" + serviceProviderCode + "无法找到合作商");
                    }
                    if (merchant.getIsSelf() == MerchantOperationMode.principal.value()) {
                        // 如果分润方是电桩自营的
                        orderInfo.setRealReceiver(serviceProviderCode);
                    }
                }
                orderInfo.setCaculatedTotalPrice(
                        AmountUtil.add(orderInfo.getCaculatedTotalPrice(), orderItem.getRealTotalPrice()));
                // 将计算得到的OrderItem对象的部分属性放入ServicePriceVO中作为结果返回
                ServicePriceVO servicePriceVO = new ServicePriceVO();
                servicePriceVO.setServiceNo(orderItem.getServiceNo());
                servicePriceVO.setServiceName(orderServiceInfo.getName());
                servicePriceVO.setBuyNum(orderItem.getBuyNum());
                servicePriceVO.setOriginalPrice(orderItem.getTotalPrice());
                servicePriceVO.setRealPrice(orderItem.getRealTotalPrice());
                servicePriceVOList.add(servicePriceVO);
            }
            boolean isNotPay = orderInfo.getCaculatedTotalPrice().compareTo(new BigDecimal(0)) == 0;
            boolean sendAccountingStatus = false;
            if (isNotPay || OrderAppConfig.GET().getAccountingNotSendCardType().contains(orderInfo.getCardType())) {
                // 若当前订单真实金额为0,则表示不需要支付，支付渠道为免收费，不需要发送台帐
                orderInfo.setStatus(OrderStatus.payedDone.value());
                orderInfo.setPayTypeCode(OrderPayWay.FREE_PAY.value());
            } else {
                // 支付状态以及台帐发送
                if (orderInfo.getCardType() != null) {
                    if (orderInfo.getCardType().equals(CardType.OFFLINE_CARD.value())) {
                        orderInfo.setPayTypeCode(payType);
                        orderInfo.setStatus(orderBaseData0.getPayStatus());
                        if (OrderStatus.payedDone.value() == payStatus && OrderPayWay.FREE_PAY != payWay) {
                            // 当前支付方式不能为免支付，若是免支付，则不会进行账务统计
                            // 生成订单发送台帐状态信息
                            sendAccountingStatus = true;
                        }
                    } else if (orderInfo.getCardType().equals(CardType.IDENTITY_CARD.value())) {
                        orderInfo.setPayTypeCode(OrderPayWay.unify.value());
                        orderInfo.setStatus(payStatus);
                        sendAccountingStatus = true;
                    } else if (orderInfo.getCardType().equals(CardType.ONLINE_CARD.value())
                            && !orderInfo.getAppId().equals(BizSystemCode.DzApp.value())) {
                        orderInfo.setPayTypeCode(OrderPayWay.enterprise.value());
                        orderInfo.setStatus(payStatus);
                        sendAccountingStatus = true;
                    }
                    log.info("当前创建订单中,订单号:" + orderInfo.getOrderNo() + ",卡类型为："
                            + String.valueOf(orderInfo.getCardType()) + "，支付状态:" + String.valueOf(orderInfo.getStatus())
                            + "，支付类别:" + String.valueOf(orderInfo.getPayTypeCode()));
                }
            }
            orderInfo.save();
            if (sendAccountingStatus) {
                // 生成订单发送台帐状态信息
                OrderAccountingStatus oas = new OrderAccountingStatus();
                oas.setOrderNo(orderInfo.getOrderNo());
                oas.save();
            }
            createdOrderVO.setTotalFee(orderInfo.getCaculatedTotalPrice());
            createdOrderVO.setOrderItemVOList(servicePriceVOList);
        }
        return createdOrderVO;
    }

    /**
     * 修改订单状态
     *
     * @param sourceOrder
     * @throws BusinessException
     */
    @OrderLogAnnotation(bizCode = "modifyOrderStatus", bizName = "修改订单状态", bizType = BizType.BUSINESS)
    public void modifyOrderStatus(OrderInfo sourceOrder) throws BusinessException {
        log.info("更改订单状态service层, sourceOrder:", sourceOrder);
        if (sourceOrder != null && StringUtils.isNotEmpty(sourceOrder.getOrderNo())) {
            if (sourceOrder.getStatus() == null) {
                throw new BusinessException("传入的订单状态为空！");
            }
            OrderInfo destOrder = OrderInfo.getById(sourceOrder.getOrderNo());
            if (destOrder == null) {
                throw new BusinessException("传入的订单对象无法在数据库查询出匹配对象！");
            }
            if (!CardType.OFFLINE_CARD.value().equals(destOrder.getCardType())) {
                throw new BusinessException("传入的订单所匹配的用户不是使用的线下卡！");
            }
            if (!destOrder.getCaculatedTotalPrice().equals(sourceOrder.getCaculatedTotalPrice())) {
                throw new BusinessException("传入的订单实际应付的总价不匹配！");
            }
            destOrder.setStatus(sourceOrder.getStatus());
            if (OrderStatus.payedDone.value() == sourceOrder.getStatus()) {
                // 生成订单发送台帐状态信息
                OrderAccountingStatus oas = new OrderAccountingStatus();
                oas.setOrderNo(sourceOrder.getOrderNo());
                oas.save();
            }
            destOrder.update();
        } else {
            throw new BusinessException("传入的参数为空！");
        }
    }

    /**
     * 预付款下单请求处理方法<br>
     * 当前业务逻辑:<br>
     * 首先对当前数据进行数据校验<br>
     * 再次处理主服务编号<br>
     * 然后处理用户类型,若用户为空，并且卡类型不能线下卡<br>
     * 然后处理订单项：<br>
     * --{<br>
     * 1.vo转换成OrderBaseData<br>
     * 2.根据当前订单阶段，进行相关的订单项打折计算<br>
     * 3.保存订单项<br>
     * 4. 分润信息处理：<br>
     * ----{<br>
     * ----1.vo转换成OrderBaseData<br>
     * ----2.根据当前订单阶段，进行相关的订单项打折计算<br>
     * ----}<br>
     * ----注意：在非收入阶段，都可以理解为每项都是电桩自营的利润项目，则分润则分配到自营中，来源于调用端传入 --}<br>
     *
     * @param advanceOrder 预付款下单的vo
     * @return
     * @throws BusinessException
     */
    @OrderLogAnnotation(bizCode = "createAdvanceOrder", bizName = "预付款下单", bizType = BizType.BUSINESS)
    public CreatedOrderVO createAdvanceOrder(AdvanceOrder advanceOrder) throws BusinessException {
        log.info("下单请求service层, advanceOrder:", advanceOrder);
        CreatedOrderVO createdOrderVO = new CreatedOrderVO();
        List<ServicePriceVO> servicePriceVOList = new ArrayList<ServicePriceVO>();
        if (advanceOrder == null) {
            throw new ParamNotFoundInSystemException("预付款下单信息为空");
        }
        // 校验
        advanceOrder.validate();
        // 处理主服务编号
        advanceOrder.dealMainServiceNo();
        OrderInfo orderInfo = new OrderInfo();
        // 预付款订单类别
        int orderType = OrderConstant.OrderType.ADVANCE_PAYMENT.value();
        // 订单阶段值
        int stage = advanceOrder.getPaymentStage();
        // 当前订单阶段
        AdvancePaymentStage advancePaymentStage = advanceOrder.getAdvancePaymentStage();
        boolean isIncome = AdvancePaymentStage.isInCome(advancePaymentStage);
        String cardType = advanceOrder.getCardType();
        String cardNo = advanceOrder.getCardNo();
        String appId = advanceOrder.getAppId();
        UserInfo user = UserInfo.getUserInfoBy(cardType, cardNo);
        // 处理用户类型
        if (user == null && !cardType.equals(CardType.OFFLINE_CARD.value())) {
            throw new ParamNotFoundInSystemException("通过卡类型和卡号无法找到关联的用户");
        }
        if (user != null) {
            advanceOrder.setUserId(user.getUserId());
            advanceOrder.setUserType(user.getUserType().toString());
        } else {
            advanceOrder.setUserType(String.valueOf(UserType.offline_customer.value()));
        }
        orderInfo.setCardNo(cardNo);
        orderInfo.setCardType(cardType);
        orderInfo.setAppId(appId);
        orderInfo.setOrderType(orderType);
        orderInfo.setStage(stage);
        orderInfo.setUserId(advanceOrder.getUserId());
        orderInfo.setUserType(advanceOrder.getUserType());
        orderInfo.setPayerBalance(advanceOrder.getPayerBalance());
        // 订单的主服务编号
        orderInfo.setServiceNo(advanceOrder.getMainServiceNo());
        // 生成订单号
        String orderNo = advanceOrder.generalOrderNo();
        orderInfo.setOrderNo(orderNo);
        String relateNo = advanceOrder.generalRelateNo(orderNo);
        orderInfo.setRelatedOrderNo(relateNo);
        createdOrderVO.setOrderNo(orderInfo.getOrderNo());
        createdOrderVO.setMainServiceName(advanceOrder.getMainServiceName());
        OrderBaseData orderBaseData;
        List<OrderBaseData> orderBaseDatas = new ArrayList<OrderBaseData>();
        for (AdvanceOrderItem advanceOrderItem : advanceOrder.getOrderItems()) {
            // 转换，将AdvanceOrderItem的 属性转换成OrderBaseData对象
            orderBaseData = advanceOrderItem.convertOrderBaseData();
            // 属性拷贝
            advanceOrder.copyPropertiesToOrderBaseData(orderBaseData);
            // 转移值，将订单中当前的电桩编号以及电站Id传递到分层数据结构之中
            // 若订单项中存在电站Id，以及桩号，则直接拷贝到分润信息之中
            if (orderBaseData.getDivideInfo() != null) {
                orderBaseData.getDivideInfo().setPlantId(orderBaseData.getPlantId());
                orderBaseData.getDivideInfo().setKeyLink(orderBaseData.getEquipmentNo());
            }

            orderBaseData.setUserId(orderInfo.getUserId());
            orderBaseData.setUserType(orderInfo.getUserType());
            ProviderService providerService = ProviderService.getProviderServiceBy(orderBaseData.getServiceNo(),
                    orderBaseData.getServiceProviderCode());
            if (providerService == null) {
                throw new ParamNotFoundInSystemException("通过serviceNo：" + orderBaseData.getServiceNo()
                        + "和serviceProviderCode：" + orderBaseData.getServiceProviderCode() + "无法找到服务与服务提供商的关联关系");
            }
            orderBaseData.setIsCost(providerService.getIsCost());
            orderBaseData.setUnitNo(providerService.getUnitNo());
            // 服务的原始单价
            BigDecimal unitPrice = orderBaseData.getUnitPrice();
            // 获取白名单打折信息
            WhiteListInfo whiteListInfo = orderBaseData.getWhiteListInfo();
            if (unitPrice != null && whiteListInfo != null) {
                BigDecimal disCount = whiteListInfo.getDiscount();
                if (disCount != null) {
                    unitPrice = AmountUtil.multiply(unitPrice, disCount);
                }
            }
            orderBaseData.setUnitPrice(unitPrice);
            orderBaseDatas.add(orderBaseData);
        }

        // 预付款根据不同的状态，计算项不一样的业务逻辑
        List<OrderItem> orderItems = advanceOrder.caculate(orderBaseDatas, activityRuleService);
        for (OrderItem orderItem : orderItems) {
            // 获取分润信息并计算
            orderBaseData = orderItem.getOrderBaseData();
            if (orderBaseData == null) {
                // 当前订单项缺少原始的订单项数据
                throw new BusinessException("当前订单项缺少原始的订单项数据");
            }
            DivideInfo divideInfo = orderBaseData.getDivideInfo();
            if ((!isIncome) && divideInfo != null) {
                // 当前并不是收入状态，但存在分润信息，则会出现业务错误
                throw new BusinessException("当前订单状态，并不是收入阶段，不存在收入项也就不会存在分润信息");
            }
            // 订单项保存
            orderBaseData = orderItem.getOrderBaseData();
            OrderServiceInfo orderServiceInfo = OrderServiceInfo.getById(orderBaseData.getServiceNo());
            orderItem.setOrderNo(orderInfo.getOrderNo());
            orderItem.setIsCost(orderBaseData.getIsCost());
            orderItem.setItemId(DigestUtils.md5Hex(orderInfo.getOrderNo() + orderItem.getServiceNo()
                    + orderItem.getServiceProvider() + System.nanoTime()));
            orderItem.save();
            // 当前的订单状态是收入阶段的时候，才存在分润信息
            if (isIncome) {
                // 收入阶段
                if (divideInfo != null) {
                    String merchantCodeStr = divideInfo.getMerchantCodes();
                    String[] merchantCodes = merchantCodeStr.split(",");
                    String ratioStr = divideInfo.getRatios();
                    String[] ratios = ratioStr.split(",");
                    String minAmountStr = divideInfo.getMinAmount();
                    // 保底金额（以逗号分隔）(传空值，则表明每一个保定金额都为0，反之将每个分润商的保底金额传递过来)
                    boolean hasMinAmount = !StringUtils.isEmpty(minAmountStr);
                    String[] minAmounts = null;
                    if (hasMinAmount) {
                        // 若有传递任何分润商的信息的时候
                        minAmounts = minAmountStr.split(",");
                        if (merchantCodes.length != minAmounts.length) {
                            throw new BusinessException("分润计算时获取传过来的merchantCode与保底金额信息个数不一致");
                        }
                    }
                    BigDecimal dividedSum = new BigDecimal("0.00");
                    String curMinAmountStr;
                    for (int i = 0; i < merchantCodes.length; i++) {
                        // 初始化保底金额
                        // 传过来中存在保底金额的时候 就从数组之中获取，反之没有传过来保底金额的时候，默认为0
                        curMinAmountStr = hasMinAmount ? minAmounts[i] : "0.00";
                        String merchantCode = merchantCodes[i];
                        Merchant merchant = Merchant.getById(merchantCode);
                        if (merchant == null) {
                            throw new BusinessException("分润计算时通过merchantCode：" + merchantCode + "无法找到合作商");
                        }
                        if (merchant.getIsSelf() == MerchantOperationMode.principal.value()) {
                            // 如果分润方是电桩自营的
                            orderInfo.setRealReceiver(merchantCode);
                        }
                        BigDecimal ratio = new BigDecimal(ratios[i]);
                        BigDecimal minAmount = new BigDecimal(curMinAmountStr);
                        BigDecimal splitedPrice = AmountUtil.multiply(orderItem.getRealTotalPrice(), ratio);
                        if (i == merchantCodes.length - 1) {
                            splitedPrice = AmountUtil.sub(orderItem.getRealTotalPrice(), dividedSum);
                        }
                        OrderItemDividedDetail orderItemDividedDetail = new OrderItemDividedDetail(orderItem,
                                merchantCode, ratio, minAmount, splitedPrice);
                        dividedSum = AmountUtil.add(dividedSum, splitedPrice);
                        orderItemDividedDetail.save();
                    }
                } else {
                    OrderItemDividedDetail orderItemDividedDetail = new OrderItemDividedDetail(orderItem);
                    orderItemDividedDetail.save();
                    String serviceProviderCode = orderItem.getServiceProvider();
                    Merchant merchant = Merchant.getById(serviceProviderCode);
                    if (merchant == null) {
                        throw new BusinessException("通过serviceProviderCode：" + serviceProviderCode + "无法找到合作商");
                    }
                    if (merchant.getIsSelf() == MerchantOperationMode.principal.value()) {
                        // 如果分润方是电桩自营的
                        orderInfo.setRealReceiver(serviceProviderCode);
                    }
                }
            } else {
                // 其他预付款阶段以及差额平衡阶段，都可以理解为电桩自营的项目
                OrderItemDividedDetail orderItemDividedDetail = new OrderItemDividedDetail(orderItem);
                orderItemDividedDetail.save();
                String serviceProviderCode = orderItem.getServiceProvider();
                Merchant merchant = Merchant.getById(serviceProviderCode);
                if (merchant == null) {
                    throw new BusinessException("通过serviceProviderCode：" + serviceProviderCode + "无法找到合作商");
                }
                if (merchant.getIsSelf() == MerchantOperationMode.principal.value()) {
                    // 如果分润方是电桩自营的
                    orderInfo.setRealReceiver(serviceProviderCode);
                }
            }
            // 当前订单项计算出这个订单的真实价格
            orderInfo.setCaculatedTotalPrice(
                    AmountUtil.add(orderInfo.getCaculatedTotalPrice(), orderItem.getRealTotalPrice()));
            // 将计算得到的OrderItem对象的部分属性放入ServicePriceVO中作为结果返回
            ServicePriceVO servicePriceVO = new ServicePriceVO();
            servicePriceVO.setServiceNo(orderItem.getServiceNo());
            servicePriceVO.setServiceName(orderServiceInfo.getName());
            servicePriceVO.setBuyNum(orderItem.getBuyNum());
            servicePriceVO.setOriginalPrice(orderItem.getTotalPrice());
            servicePriceVO.setRealPrice(orderItem.getRealTotalPrice());
            servicePriceVO.setItemId(orderItem.getItemId());
            servicePriceVOList.add(servicePriceVO);
        }
        // 后续业务计算--新订单持久化到数据库
        advanceOrder.postService(orderInfo, orderItems);
        createdOrderVO.setTotalFee(orderInfo.getCaculatedTotalPrice());
        createdOrderVO.setOrderItemVOList(servicePriceVOList);
        return createdOrderVO;
    }

    /**
     * 根据订单号查询生成的订单信息
     *
     * @param orderNo
     * @return CreatedOrderVO的JSON字符串
     */
    public String getCreatedOrderVO(String orderNo) {
        log.info("根据订单号查询生成的订单信息service层, orderNo:", orderNo);
        CreatedOrderVO createdOrderVO = new CreatedOrderVO();
        List<ServicePriceVO> servicePriceVOList = new ArrayList<ServicePriceVO>();
        OrderInfo order = OrderInfo.getById(orderNo);
        List<OrderItem> orderItems = OrderItem.getByOrderNo(orderNo);
        for (OrderItem orderItem : orderItems) {
            ServicePriceVO spv = new ServicePriceVO();
            spv.setServiceNo(orderItem.getServiceNo());
            OrderServiceInfo serviceInfo = OrderServiceInfo.getById(orderItem.getServiceNo());
            spv.setServiceName(serviceInfo.getName());
            spv.setBuyNum(orderItem.getBuyNum());
            spv.setOriginalPrice(orderItem.getTotalPrice());
            spv.setRealPrice(orderItem.getRealTotalPrice());
            servicePriceVOList.add(spv);
        }
        createdOrderVO.setOrderNo(orderNo);
        OrderServiceInfo mainServiceInfo = OrderServiceInfo.getById(order.getServiceNo());
        createdOrderVO.setMainServiceName(mainServiceInfo.getName());
        createdOrderVO.setTotalFee(order.getCaculatedTotalPrice());
        createdOrderVO.setOrderItemVOList(servicePriceVOList);
        return JSON.toJSONStringWithDateFormat(createdOrderVO, "yyyy-MM-dd HH:mm:ss",
                SerializerFeature.WriteDateUseDateFormat);
    }

    /**
     * 预付款查询<br>
     * 第一阶段(预付款阶段)以及第三阶段(差额平衡阶段),不需要进行drools处理
     *
     * @param advanceOrder
     * @return
     * @throws BusinessException
     */
    public CreatedOrderVO advanceServicePriceQuery(AdvanceOrder advanceOrder) throws BusinessException {
        log.info("预付款询价请求service层, advanceOrder:", advanceOrder);
        CreatedOrderVO createdOrderVO = new CreatedOrderVO();
        List<ServicePriceVO> servicePriceVOList = new ArrayList<ServicePriceVO>();
        if (advanceOrder == null) {
            throw new ParamNotFoundInSystemException("预付款询价信息为空");
        }
        // 校验
        advanceOrder.validate();
        // 处理主服务编号
        advanceOrder.dealMainServiceNo();
        String cardType = advanceOrder.getCardType();
        String cardNo = advanceOrder.getCardNo();
        UserInfo user = UserInfo.getUserInfoBy(cardType, cardNo);
        // 处理用户类型
        if (user == null && !cardType.equals(CardType.OFFLINE_CARD.value())) {
            throw new ParamNotFoundInSystemException("通过卡类型和卡号无法找到关联的用户");
        }
        if (user != null) {
            advanceOrder.setUserId(user.getUserId());
            advanceOrder.setUserType(user.getUserType().toString());
        } else {
            advanceOrder.setUserType(String.valueOf(UserType.offline_customer.value()));
        }
        createdOrderVO.setMainServiceName(advanceOrder.getMainServiceName());
        OrderBaseData orderBaseData = null;
        List<OrderBaseData> orderBaseDatas = new ArrayList<OrderBaseData>();
        for (AdvanceOrderItem advanceOrderItem : advanceOrder.getOrderItems()) {
            // 转换，将AdvanceOrderItem的 属性转换成OrderBaseData对象
            orderBaseData = advanceOrderItem.convertOrderBaseData();
            // 属性拷贝
            advanceOrder.copyPropertiesToOrderBaseData(orderBaseData);
            // 转移值，将订单中当前的电桩编号以及电站Id传递到分层数据结构之中
            // 若订单项中存在电站Id，以及桩号，则直接拷贝到分润信息之中
            if (orderBaseData.getDivideInfo() != null) {
                orderBaseData.getDivideInfo().setPlantId(orderBaseData.getPlantId());
                orderBaseData.getDivideInfo().setKeyLink(orderBaseData.getEquipmentNo());
            }
            orderBaseData.setUserId(advanceOrder.getUserId());
            orderBaseData.setUserType(advanceOrder.getUserType());
            ProviderService providerService = ProviderService.getProviderServiceBy(orderBaseData.getServiceNo(),
                    orderBaseData.getServiceProviderCode());
            if (providerService == null) {
                throw new ParamNotFoundInSystemException("通过serviceNo：" + orderBaseData.getServiceNo()
                        + "和serviceProviderCode：" + orderBaseData.getServiceProviderCode() + "无法找到服务与服务提供商的关联关系");
            }
            orderBaseData.setIsCost(providerService.getIsCost());
            orderBaseData.setUnitNo(providerService.getUnitNo());
            // 服务的原始单价
            BigDecimal unitPrice = orderBaseData.getUnitPrice();
            // 获取白名单打折信息
            WhiteListInfo whiteListInfo = orderBaseData.getWhiteListInfo();
            if (unitPrice != null && whiteListInfo != null) {
                BigDecimal disCount = whiteListInfo.getDiscount();
                if (disCount != null) {
                    unitPrice = AmountUtil.multiply(unitPrice, disCount);
                }
            }
            orderBaseData.setUnitPrice(unitPrice);
            orderBaseDatas.add(orderBaseData);
        }
        // 预付款根据不同的状态，计算项不一样的业务逻辑
        List<OrderItem> orderItems = advanceOrder.caculate(orderBaseDatas, activityRuleService);
        BigDecimal sumMoney = new BigDecimal(0);
        for (OrderItem orderItem : orderItems) {
            // 将计算得到的OrderItem对象的部分属性放入ServicePriceVO中作为查询结果返回
            ServicePriceVO servicePriceVO = new ServicePriceVO();
            servicePriceVO.setServiceNo(orderItem.getServiceNo());
            OrderServiceInfo serviceInfo = OrderServiceInfo.getById(orderItem.getServiceNo());
            servicePriceVO.setServiceName(serviceInfo.getName());
            servicePriceVO.setBuyNum(orderItem.getBuyNum());
            servicePriceVO.setOriginalPrice(orderItem.getTotalPrice());
            servicePriceVO.setRealPrice(orderItem.getRealTotalPrice());
            servicePriceVO.setItemId(orderItem.getItemId());
            servicePriceVOList.add(servicePriceVO);
            sumMoney = AmountUtil.add(sumMoney, orderItem.getRealTotalPrice());
        }
        createdOrderVO.setMainServiceNo(createdOrderVO.getMainServiceNo());
        createdOrderVO.setMainServiceName(createdOrderVO.getMainServiceName());
        createdOrderVO.setTotalFee(sumMoney);
        createdOrderVO.setOrderItemVOList(servicePriceVOList);
        return createdOrderVO;
    }

    /**
     * 接收主服务器的回调后，将订单状态改为已支付/完成
     *
     * @param orderNoStr 订单号,可以逗号分隔
     */
    @OrderLogAnnotation(bizCode = "unifyAndCorpPay", bizName = "统付/企业支付回调", bizType = BizType.BUSINESS)
    public void transChangeOrderStatusToDone(String orderNoStr) {
        log.info("unifyAndCorpPay, orderNos:", orderNoStr);
        String[] orderNos = orderNoStr.split(",");
        List<String> orderNoList = new ArrayList<String>(orderNos.length);
        for (String orderNo : orderNos) {
            orderNoList.add(orderNo);
        }
        OrderInfo.changeOrderStatus(orderNoList, OrderStatus.payedDone.value());
    }

    /**
     * 用户发起支付时的处理
     *
     * @param  userPayInfoVO 订单号,可以逗号分隔
     */
    @OrderLogAnnotation(bizCode = "userPaying", bizName = "用户发起支付", bizType = BizType.BUSINESS)
    public void transUserPaying(UserPayInfoVO userPayInfoVO) {
        log.info("用户正在支付service层,userPayInfoVO:", userPayInfoVO);
        String cardNo = userPayInfoVO.getCardNo();
        String cardType = userPayInfoVO.getCardType();
        UserInfo user = UserInfo.getUserInfoBy(cardType, cardNo);
        if (user != null) {
            // 非线下现金卡的时候
            userPayInfoVO.setPayer(user.getUserId());
            if (userPayInfoVO.getPayTypeCode() == OrderPayWay.unify.value()
                    || userPayInfoVO.getPayTypeCode() == OrderPayWay.enterprise.value()) {
                // 如果是统付或者企业客户支付
                userPayInfoVO.setPayer(user.getMerchantCode());
            }
        }
        if (userPayInfoVO.getPayTypeCode() != OrderPayWay.thirdImmediately.value()) {
            // 生成订单发送台帐状态信息
            OrderAccountingStatus oas = new OrderAccountingStatus();
            oas.setOrderNo(userPayInfoVO.getOrderNo());
            oas.save();
        }
        // 修改订单支付信息及状态
        OrderInfo.updateOrderOnPaying(userPayInfoVO);
    }

    /**
     * 有贝先付回调处理服务
     *
     * @param params 有贝先付回调传递过来的JSON字符串
     * @return JSON字符串，包括交易结果代码、交易结果描述
     */
    public String transYouBeiPayCallBack(Map<String, String> params) {
        log.info("有贝先付回调处理service层, params:", params);
        String orderNo = params.get("no_order");
        // 查询订单回调记录是否存在
        YouBeiPayCallBackRecord youBeiPayCallBackRecord = YouBeiPayCallBackRecord.getBy(orderNo);
        if (youBeiPayCallBackRecord == null) {
            youBeiPayCallBackRecord = new YouBeiPayCallBackRecord(params);
            // 新增回调记录
            youBeiPayCallBackRecord.save();
            // 生成订单发送台帐状态信息
            OrderAccountingStatus oas = new OrderAccountingStatus();
            oas.setOrderNo(orderNo);
            oas.save();
        } else {
            youBeiPayCallBackRecord = new YouBeiPayCallBackRecord(params);
            // 更新回调记录
            youBeiPayCallBackRecord.update();
        }
        // 支付成功，修改订单信息
        OrderInfo.updateOrderAfterYouBeiPayBack(youBeiPayCallBackRecord);
        return YouBeiPayUtil.RET_SUCCESS_JSON;
    }

    /**
     * 支付宝支付回调处理服务
     *
     * @param params 支付宝支付回调参数
     * @return success/fail
     */
    public String transAliPayCallBack(Map<String, String> params) {
        log.info("支付宝支付回调处理service层,params:", params);
        String orderNo = params.get("out_trade_no");
        // 查询订单回调记录是否存在
        AliPayCallBackRecord aliPayCallBackRecord = AliPayCallBackRecord.getBy(orderNo);
        if (aliPayCallBackRecord == null) {
            aliPayCallBackRecord = new AliPayCallBackRecord(params);
            // 新增回调记录
            aliPayCallBackRecord.save();
            // 生成订单发送台帐状态信息
            OrderAccountingStatus oas = new OrderAccountingStatus();
            oas.setOrderNo(orderNo);
            oas.save();
        } else {
            aliPayCallBackRecord = new AliPayCallBackRecord(params);
            // 更新回调记录
            aliPayCallBackRecord.update();
        }
        // 支付成功，修改订单信息
        OrderInfo.updateOrderAfterALiPayBack(aliPayCallBackRecord);
        return AliPayUtil.RET_SUCCESS_STR;
    }

    /**
     * 支付宝支付回调处理服务
     *
     * @param params 支付宝支付回调参数
     * @return success/fail
     */
    public String transAliPay2CallBack(Map<String, String> params) {
        log.info("支付宝支付转账回调处理service层,params:", params);
        String orderNo = params.get("out_trade_no");
        // 查询订单回调记录是否存在
        AliPayCallBackRecord aliPayCallBackRecord = AliPayCallBackRecord.getBy(orderNo);
        if (aliPayCallBackRecord == null) {
            aliPayCallBackRecord = new AliPayCallBackRecord(params);
            // 新增回调记录
            aliPayCallBackRecord.save();
        } else {
            aliPayCallBackRecord = new AliPayCallBackRecord(params);
            // 更新回调记录
            aliPayCallBackRecord.update();
        }
        // 支付成功，修改订单信息
        OrderPayInfo.updateOrderAfterALiPayBack(aliPayCallBackRecord);
        return AliPayUtil.RET_SUCCESS_STR;
    }

    /**
     * 微信支付回调处理服务
     *
     * @param params 微信支付回调参数
     * @return xml
     */
    public String transWeiXinPayCallBack(Map<String, Object> params) {
        log.info("微信支付回调处理service层,callBackMap:", params);
        String orderNo = (String) params.get("out_trade_no");
        WeiXinPayCallBackRecord weixinPayCallBackRecord = WeiXinPayCallBackRecord.getBy(orderNo);
        // 查询订单回调记录是否存在
        if (weixinPayCallBackRecord == null) {
            // 新增回调记录
            weixinPayCallBackRecord = new WeiXinPayCallBackRecord(params);
            weixinPayCallBackRecord.save();
            // 生成订单发送台帐状态信息
            OrderAccountingStatus oas = new OrderAccountingStatus();
            oas.setOrderNo(orderNo);
            oas.save();
        } else {
            // 更新回调记录
            weixinPayCallBackRecord = new WeiXinPayCallBackRecord(params);
            weixinPayCallBackRecord.update();
        }
        // 支付成功，修改订单信息
        OrderInfo.updateOrderAfterWeiXinPayBack(weixinPayCallBackRecord);
        return WeiXinPayUtilBase.RET_SUCCESS_XML;
    }

    /**
     * 支付宝充值到现金卡回调处理服务<br>
     * 能进入到当前的说明支付宝回调成功<br>
     * 当前业务逻辑：新增或者更新阿里支付回调结果信息，并尝试向主服务器调用现金充值接口,<br>
     * 若首次调用结果是失败，则会继续尝试3次，直到某一次成功为止，否则，则输出错误日志
     *
     * @param params 支付宝支付回调参数
     * @return success/fail
     */
    public String transAliPayRechargeCashCardCallback(Map<String, String> params) {
        log.info("支付宝充值到现金卡回调服务处理service层,params:", params);
        String orderNo = params.get("out_trade_no");
        // 查询订单回调记录是否存在
        AliPayCallBackRecord aliPayCallBackRecord = AliPayCallBackRecord.getBy(orderNo);
        if (aliPayCallBackRecord == null) {
            aliPayCallBackRecord = new AliPayCallBackRecord(params);
            // 新增回调记录
            aliPayCallBackRecord.save();
        } else {
            aliPayCallBackRecord = new AliPayCallBackRecord(params);
            // 更新回调记录
            aliPayCallBackRecord.update();
        }
        // 支付成功，向主服务器发送现金卡充值
        try {
            RechargeOnlineAccount rechargeOnlineAccount = new RechargeOnlineAccount(aliPayCallBackRecord);
            if (rechargeOnlineAccount != null) {
                MsRpcClient msRpcClient = SysApplicationContextAware.getBean(MsRpcClient.class);
                String result = msRpcClient.rechargeOnlineAccount(rechargeOnlineAccount);
                boolean isOperationSuccess = msRpcClient.isRpcOperationSuccess(result);
                if (!isOperationSuccess) {
                    // 若第一次尝试失败，则会连续尝试3次向主服务器发送数据
                    log.info("支付成功，向主服务器发送现金卡充值rpc首次失败[orderNo=" + orderNo + "]", aliPayCallBackRecord);
                    // 尝试的次数
                    int count = 3;
                    for (int i = count; i > 0; i--) {
                        result = msRpcClient.rechargeOnlineAccount(rechargeOnlineAccount);
                        isOperationSuccess = msRpcClient.isRpcOperationSuccess(result);
                        if (isOperationSuccess) {
                            break;
                        } else {
                            try {
                                Thread.sleep(5 * 1000L);
                            } catch (InterruptedException e) {
                                log.error("支付成功，向主服务器发送现金卡充值rpc失败，并尝试了调用[次数=" + (count - i) + "][orderNo=" + orderNo
                                        + "]接口,等待异常", e);
                            }
                        }
                    }
                }
                if (!isOperationSuccess) {
                    log.error("支付成功，向主服务器发送现金卡充值rpc失败，并尝试了至少3次调用[orderNo=" + orderNo + "]接口", aliPayCallBackRecord);
                } else {
                    log.info("支付宝充值到现金卡回调服务处理service层完成");
                }
            }
        } catch (BusinessException e) {
            log.error("支付成功，向主服务器发送现金卡充值转换异常[orderNo=" + orderNo + "]", e);
        }
        return AliPayUtil.RET_SUCCESS_STR;
    }

    /**
     * 用户取消充电预约
     *
     * @param userId  用户Id
     * @param orderNo 充电预约的订单号
     */
    @OrderLogAnnotation(bizCode = "userCancelChargeAppointment", bizName = "用户取消充电预约", bizType = BizType.BUSINESS)
    public RetVO transUserCancelChargeAppointment(String userId, String orderNo)
            throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
        log.info("用户取消充电预约service层,userId，orderNo：", userId + "," + orderNo);
        RetVO retVO = new RetVO(RetVO.SuccessCode, null, null);
        // 获取充电预约订单项
        OrderItem chargeAppointmentOrderItem = OrderItem.getChargeAppointmentOrderItemBy(userId, orderNo);
        if (chargeAppointmentOrderItem == null) {
            log.error("用户取消充电预约失败:无效的订单号,orderNo：" + orderNo);
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        OrderInfo chargeAppointmentOrder = OrderInfo.getById(orderNo);
        if (chargeAppointmentOrder == null) {
            log.error("用户取消充电预约失败:无效的订单号,orderNo：" + orderNo);
            retVO.setRetCode(RetVO.FailCode);
            retVO.setErrorMsg("无效的订单号,orderNo：" + orderNo);
            return retVO;
        }
        if (chargeAppointmentOrder.getStatus() != OrderStatus.payedDone.value()) {
            // 如果该充电预约订单的状态不为"已支付，已完成"
            retVO.setRetCode(RetVO.FailCode);
            retVO.setErrorMsg("订单状态不为已支付，已完成，orderNo：" + orderNo);
            return retVO;
        }
        // 获取当前时间
        Calendar now = Calendar.getInstance();
        // 充电预约开始时间
        Calendar chargeAppointmentStartTime = Calendar.getInstance();
        chargeAppointmentStartTime.setTime(chargeAppointmentOrderItem.getStartTime());
        // 充电预约时间,单位是分钟
        int buyNum = chargeAppointmentOrderItem.getBuyNum().intValue();
        chargeAppointmentStartTime.add(Calendar.MINUTE, buyNum);
        // 毫秒数
        long ms = chargeAppointmentStartTime.getTimeInMillis() - now.getTimeInMillis();
        if (ms <= 0) {
            // 如果当前时间达到或超过了充电预约的截止时间
            chargeAppointmentOrder.setStatus(OrderStatus.overdueDone.value());
            chargeAppointmentOrder.update();
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        // 有几个15分钟的钱需要退给用户
        int retNum = (int) (ms / OrderConstant.Fifteen_MINUTE_INT);
        if (retNum == 0) {
            chargeAppointmentOrder.setStatus(OrderStatus.overdueDone.value());
            chargeAppointmentOrder.update();
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        BigDecimal retBuyNum = new BigDecimal(retNum);
        // 用充电预约订单的部分属性生成预约退款订单
        OrderInfo refundOrder = (OrderInfo) BeanUtils.cloneBean(chargeAppointmentOrder);
        // 生成预约退款订单的订单号，并设置
        String refundOrderId = new StringBuilder(refundOrder.getUserType()).append(refundOrder.getAppId())
                .append(UUIDUtil.getCurrentDate14(now.getTime())).append(UUIDUtil.randomNum(4)).toString();
        chargeAppointmentOrder.setRelatedOrderNo(refundOrderId);
        chargeAppointmentOrder.setStatus(OrderStatus.canceledDone.value());
        chargeAppointmentOrder.update();
        refundOrder.setOrderNo(refundOrderId);
        refundOrder.setRelatedOrderNo(chargeAppointmentOrder.getOrderNo());
        refundOrder.setStatus(OrderStatus.unPay.value());
        OrderItem refundOrderItem = (OrderItem) BeanUtils.cloneBean(chargeAppointmentOrderItem);
        refundOrderItem.setOrderNo(refundOrderId);
        refundOrderItem.setServiceNo(OrderServiceEnum.ChargeAppointmentRefund.value());
        refundOrderItem.setBuyNum(retBuyNum);
        BigDecimal price = AmountUtil.multiply(retBuyNum, refundOrderItem.getUnitPrice());
        refundOrder.setCaculatedTotalPrice(price.negate());
        refundOrder.save();
        refundOrderItem.setTotalPrice(price.negate());
        refundOrderItem.setRealTotalPrice(price.negate());
        refundOrderItem.setStartTime(now.getTime());
        refundOrderItem.setEndTime(now.getTime());
        refundOrderItem.setItemId(DigestUtils.md5Hex(refundOrderItem.getOrderNo() + refundOrderItem.getServiceNo()
                + refundOrderItem.getServiceProvider() + System.nanoTime()));
        refundOrderItem.save();
        OrderItemDividedDetail refundOrderItemDividedDetail = new OrderItemDividedDetail(refundOrderItem);
        refundOrderItemDividedDetail.save();
        if (refundOrder.getPayTypeCode() == OrderPayWay.thirdImmediately.value()) {
            // 生成待发送退款请求的数据
            OrderRefundStatus crs = new OrderRefundStatus();
            crs.setOrderNo(refundOrderId);
            crs.setPayChannelCode(refundOrder.getPayChannelCode());
            crs.save();
        } else {
            // 生成订单发送台帐状态信息
            OrderAccountingStatus oas = new OrderAccountingStatus();
            oas.setOrderNo(refundOrder.getOrderNo());
            oas.save();
        }
        return retVO;
    }

    /**
     * 取消用户在某个电桩/枪上，离当前时间最近的充电预约订单
     */
    public RetVO transCancelRecentChargeAppointment(String userId, String equipmentNo, String auxEquipmentNo)
            throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
        log.info("取消用户在某个电桩上，离当前时间最近的充电预约订单service层,equipmentNo，userId：",
                equipmentNo + "," + userId + "," + auxEquipmentNo);
        RetVO retVO = new RetVO(RetVO.SuccessCode, null, null);
        // 获取当前时间
        Date now = new Date();
        Calendar c = Calendar.getInstance();
        c.add(Calendar.HOUR_OF_DAY, -6);
        Date beforeNow = c.getTime();
        // 查找用户在某个电桩上，离当前时间最近的充电预约订单
        OrderItem chargeAppointmentOrderItem = OrderItem.getChargeAppointmentOrderItemBy(userId, equipmentNo,
                auxEquipmentNo, beforeNow, beforeNow);
        if (chargeAppointmentOrderItem == null) {
            log.error("查找用户在某个电桩上，离当前时间最近的充电预约订单，未找到");
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        OrderInfo chargeAppointmentOrder = OrderInfo.getById(chargeAppointmentOrderItem.getOrderNo());
        if (chargeAppointmentOrder == null) {
            log.error("用户取消充电预约失败:无效的订单号,orderNo：" + chargeAppointmentOrderItem.getOrderNo());
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        if (chargeAppointmentOrder.getStatus() != OrderStatus.payedDone.value()) {
            // 如果该充电预约订单的状态不为"已支付，已完成"
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        // 充电预约开始时间
        Calendar chargeAppointmentStartTime = Calendar.getInstance();
        chargeAppointmentStartTime.setTime(chargeAppointmentOrderItem.getStartTime());
        // 充电预约时间,单位是分钟
        int buyNum = chargeAppointmentOrderItem.getBuyNum().intValue();
        chargeAppointmentStartTime.add(Calendar.MINUTE, buyNum);
        // 毫秒数
        long ms = chargeAppointmentStartTime.getTimeInMillis() - now.getTime();
        if (ms <= 0) {
            // 如果当前时间达到或超过了充电预约的截止时间
            chargeAppointmentOrder.setStatus(OrderStatus.overdueDone.value());
            chargeAppointmentOrder.update();
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        // 有几个15分钟的钱需要退给用户
        int retNum = (int) (ms / OrderConstant.Fifteen_MINUTE_INT);
        if (retNum == 0) {
            chargeAppointmentOrder.setStatus(OrderStatus.overdueDone.value());
            chargeAppointmentOrder.update();
            retVO.setRetCode(RetVO.FailCode);
            return retVO;
        }
        BigDecimal retBuyNum = new BigDecimal(retNum);
        // 用充电预约订单的部分属性生成预约退款订单
        OrderInfo refundOrder = (OrderInfo) BeanUtils.cloneBean(chargeAppointmentOrder);
        // 生成预约退款订单的订单号，并设置
        String refundOrderId = new StringBuilder(refundOrder.getUserType()).append(refundOrder.getAppId())
                .append(UUIDUtil.getCurrentDate14(now)).append(UUIDUtil.randomNum(4)).toString();
        chargeAppointmentOrder.setRelatedOrderNo(refundOrderId);
        chargeAppointmentOrder.setStatus(OrderStatus.canceledDone.value());
        chargeAppointmentOrder.update();
        refundOrder.setOrderNo(refundOrderId);
        refundOrder.setRelatedOrderNo(chargeAppointmentOrder.getOrderNo());
        refundOrder.setStatus(OrderStatus.unPay.value());
        OrderItem refundOrderItem = (OrderItem) BeanUtils.cloneBean(chargeAppointmentOrderItem);
        refundOrderItem.setOrderNo(refundOrderId);
        refundOrderItem.setServiceNo(OrderServiceEnum.ChargeAppointmentRefund.value());
        refundOrderItem.setBuyNum(retBuyNum);
        BigDecimal price = AmountUtil.multiply(retBuyNum, refundOrderItem.getUnitPrice());
        refundOrder.setCaculatedTotalPrice(price.negate());
        refundOrder.save();
        refundOrderItem.setTotalPrice(price.negate());
        refundOrderItem.setRealTotalPrice(price.negate());
        refundOrderItem.setStartTime(now);
        refundOrderItem.setEndTime(now);
        refundOrderItem.setItemId(DigestUtils.md5Hex(refundOrderItem.getOrderNo() + refundOrderItem.getServiceNo()
                + refundOrderItem.getServiceProvider() + System.nanoTime()));
        refundOrderItem.save();
        OrderItemDividedDetail refundOrderItemDividedDetail = new OrderItemDividedDetail(refundOrderItem);
        refundOrderItemDividedDetail.save();
        if (refundOrder.getPayTypeCode() == OrderPayWay.thirdImmediately.value()) {
            // 生成待发送退款请求的数据
            OrderRefundStatus crs = new OrderRefundStatus();
            crs.setOrderNo(refundOrderId);
            crs.setPayChannelCode(refundOrder.getPayChannelCode());
            crs.save();
        } else {
            // 生成订单发送台帐状态信息
            OrderAccountingStatus oas = new OrderAccountingStatus();
            oas.setOrderNo(refundOrder.getOrderNo());
            oas.save();
        }
        return retVO;
    }

    /**
     * 服务列表查询
     */
    public List<OrderServiceInfo> listOrderServiceInfo() {
        List<OrderServiceInfo> serviceInfoList = OrderServiceInfo.getAll();
        return serviceInfoList;
    }

    /**
     * 订单历史记录查询
     *
     * @throws BusinessException
     */
    public List<OrderHistoryQueryRetVO> orderHistoryQuery(OrderHistoryQueryParamVO orderHistoryQueryParamVO)
            throws BusinessException {
        List<OrderInfo> orderInfoList = OrderInfo.orderHistoryQuery(orderHistoryQueryParamVO);
        List<OrderHistoryQueryRetVO> retList = new ArrayList<OrderHistoryQueryRetVO>(orderInfoList.size());
        // 获取所有服务的服务号和服务名
        Map<String, String> serviceMap = OrderServiceInfo.getAllServiceCodeAndName();
        String name = "";
        if (orderInfoList.size() > 0) {
            List<String> orderNos = new ArrayList<String>();
            for (OrderInfo order : orderInfoList) {
                OrderHistoryQueryRetVO orderHistory = new OrderHistoryQueryRetVO();
                orderHistory.setOrderNo(order.getOrderNo());
                orderHistory.setRelatedOrderNo(order.getRelatedOrderNo());
                name = serviceMap.get(order.getServiceNo());
                orderHistory.setMainServiceName(name);
                orderHistory.setCaculatedTotalPrice(order.getCaculatedTotalPrice());
                orderHistory.setPayType(OrderPayWay.getDesc(order.getPayTypeCode()));
                orderHistory.setThdPayChannel(OrderPayChannelCode.getDesc(order.getPayChannelCode()));
                orderHistory.setStatus(OrderStatus.getDesc(order.getStatus()));
                orderHistory.setStatusCode(order.getStatus());
                orderHistory.setCardNo(order.getCardNo());
                orderHistory.setCreateTime(order.getCreateTime());
                orderHistory.setAttach(order.getAttach());
                orderHistory.setHide(order.getHide());
                retList.add(orderHistory);
                orderNos.add(orderHistory.getOrderNo());
            }
            /** 添加详细的订单目录信息 */
            Map<String, List<OrderItemHistoryQueryRetVO>> orderItemMap = OrderHistoryQueryVO
                    .getMergeItemsByOrderNos(orderNos);
            if (!MapUtils.isEmpty(orderItemMap)) {
                String orderNo = "";
                List<OrderItemHistoryQueryRetVO> itemDetials = null;
                for (OrderHistoryQueryRetVO orderRetVo : retList) {
                    orderNo = orderRetVo.getOrderNo();
                    itemDetials = orderItemMap.get(orderNo);
                    if (CollectionUtils.isEmpty(itemDetials)) {
                        continue;
                    }
                    orderRetVo.setItemDetials(itemDetials);
                }
            }
        }
        return retList;
    }

    /**
     * 查询某用户需要支付的订单
     *
     * @throws BusinessException
     */
    public List<CreatedOrderVO> findUserNeedPayOrders(String userId) throws BusinessException {
        List<OrderInfo> orderList = OrderInfo.findUserNeedPayOrders(userId);
        List<CreatedOrderVO> list = new ArrayList<CreatedOrderVO>();
        for (OrderInfo order : orderList) {
            CreatedOrderVO createdOrderVO = new CreatedOrderVO();
            List<ServicePriceVO> servicePriceVOList = new ArrayList<ServicePriceVO>();
            List<OrderItem> orderItems = OrderItem.getByOrderNo(order.getOrderNo());
            if (orderItems == null || orderItems.size() == 0) {
                throw new BusinessException("订单号为" + order.getOrderNo() + "的订单项为空");
            }
            for (OrderItem orderItem : orderItems) {
                ServicePriceVO spv = new ServicePriceVO();
                spv.setServiceNo(orderItem.getServiceNo());
                OrderServiceInfo serviceInfo = OrderServiceInfo.getById(orderItem.getServiceNo());
                spv.setServiceName(serviceInfo.getName());
                spv.setBuyNum(orderItem.getBuyNum());
                spv.setOriginalPrice(orderItem.getTotalPrice());
                spv.setRealPrice(orderItem.getRealTotalPrice());
                spv.setMessage(orderItem.getMessage());
                spv.setEquipmentNo(orderItem.getEquipmentNo());
                spv.setItemId(orderItem.getItemId());
                servicePriceVOList.add(spv);
            }
            createdOrderVO.setOrderNo(order.getOrderNo());
            OrderServiceInfo mainServiceInfo = OrderServiceInfo.getById(order.getServiceNo());
            createdOrderVO.setMainServiceName(mainServiceInfo.getName());
            createdOrderVO.setTotalFee(order.getCaculatedTotalPrice());
            createdOrderVO.setOrderItemVOList(servicePriceVOList);
            list.add(createdOrderVO);
        }
        return list;
    }

    /**
     * 根据订单号查询订单项
     */
    public List<OrderItem> findOrderItemsByOrderNo(String orderNo) {
        List<OrderItem> orderItemList = OrderItem.getByOrderNo(orderNo);
        return orderItemList;
    }

    /**
     * 通过订单号获取订单详细
     *
     * @param orderNo 订单号
     * @return
     * @author Anson
     * @createDate 2016年4月29日
     * @desc 订单之中的属性是简略的返回
     */
    public OrderInfoVo getOrderInfo(String orderNo) {
        OrderInfoVo vo = OrderInfoVo.getOrderInfoVo(orderNo);
        return vo;
    }

    /**
     * 通过订单号集合查询所有状态
     *
     * @param orderNos
     * @return
     * @author Anson
     * @createDate 2016年5月1日
     * @desc 通过订单号","隔开的字符串集合获取订单状态
     */
    public List<QueryOrderStatusVo> queryOrderStatus(String orderNos) {
        List<QueryOrderStatusVo> list = new ArrayList<QueryOrderStatusVo>();
        if (StringUtils.isEmpty(orderNos)) {
            return list;
        }
        String[] orderNoArr = orderNos.split(",");
        if (ArrayUtils.isEmpty(orderNoArr)) {
            return list;
        }
        List<String> orderNoList = Arrays.asList(orderNoArr);
        return QueryOrderStatusVo.queryOrderStatus(orderNoList);
    }

    /**
     * 根据订单号集合查询当前订单查询当前第三方支付信息
     *
     * @param orderNos
     * @return
     * @throws BusinessException
     */
    public List<ThdPayWayRecord> queryThdPayWayRecordbyOrderNo(String orderNos) throws BusinessException {
        List<ThdPayWayRecord> list = new ArrayList<ThdPayWayRecord>();
        if (StringUtils.isEmpty(orderNos)) {
            return list;
        }
        String[] orderArray = StringUtils.split(orderNos, ",");
        if (orderArray == null) {
            return list;
        }
        List<String> orderList = Arrays.asList(orderArray);
        ThirdRecordQueryFactory facoty = ThirdRecordQueryFactory.INSTANCE();
        OrderPayChannelCode[] codes = OrderPayChannelCode.values();
        List<ThdPayWayRecord> subList = null;
        ThirdRecordQuery query = null;
        for (OrderPayChannelCode orderPayChannelCode : codes) {
            query = facoty.get(orderPayChannelCode);
            if (query == null) {
                continue;
            }
            subList = query.query(orderList);
            if (CollectionUtils.isEmpty(subList)) {
                continue;
            }
            list.addAll(subList);
        }
        return list;
    }

    /**
     * 订单转微信订单
     *
     * @param order2WeiXinOrderRequestVo
     * @return
     * @throws BusinessException
     * @throws UnsupportedEncodingException
     * @throws DocumentException
     */
    public Order2WeiXinOrderResponseVo order2WeiXinOrder(Order2WeiXinOrderRequestVo order2WeiXinOrderRequestVo)
            throws BusinessException, UnsupportedEncodingException, DocumentException {
        Order2WeiXinOrderResponseVo order2WeiXinOrderResponseVo = new Order2WeiXinOrderResponseVo();
        OrderInfo dzOrder = getOrderByNo(order2WeiXinOrderRequestVo.getOrderno());
        if (dzOrder == null) {
            throw new BusinessException("订单:" + order2WeiXinOrderRequestVo.getOrderno() + "不存在");
        }
        if (OrderStatus.payedDone.value() == dzOrder.getStatus()) {
            throw new BusinessException("订单:" + order2WeiXinOrderRequestVo.getOrderno() + "已被支付");
        }
        log.info("dzOrder:" + dzOrder);
        String appid;
        appid = order2WeiXinOrderRequestVo.getAppId();
        // 如果请求中没有appid则使用订单中appid
        if (StringUtils.isEmpty(appid)) {
            appid = dzOrder.getAppId();
        }
        appid = appid.trim();
        String weixinAppid = "";
        String mch_id = "";
        String weixinMchKey = "";
        String weixinPayCallbackURL = "";
        if (OrderConstant.BizSystemCode.HuaTiWeiXin.value().equals(appid) || OrderConstant.BizSystemCode.DzWeiXin.value().equals(appid)) {

            weixinAppid = WeiXinPayUtilBase.getweiXinPropertieBykey(appid + "Weixin.apiKey");
            mch_id = WeiXinPayUtilBase.getweiXinPropertieBykey(appid + "Weixin.mchId");
            weixinMchKey = WeiXinPayUtilBase.getweiXinPropertieBykey(appid + "Weixin.WeixinMchKey");
            weixinPayCallbackURL = WeiXinPayUtilBase.getweiXinPropertieBykey("Weixin.weixinPayCallbackURL");
            log.info("weixinAppid:" + weixinAppid + " mch_id:" + mch_id + " weixinMchKey:" + weixinMchKey
                    + " weixinPayCallbackURL:" + weixinPayCallbackURL);
        } else {
            throw new BusinessException("当前不支持业务系统编码为:" + appid + "的微信支付");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("appid", weixinAppid);
        map.put("mch_id", mch_id);
        // 随机数
        map.put("nonce_str",
                new StringBuilder(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());

        map.put("body", order2WeiXinOrderRequestVo.getBody());
        map.put("out_trade_no", dzOrder.getOrderNo());
        // 计量单位为分 并且无小数
        BigDecimal price = AmountUtil.multiply(dzOrder.getCaculatedTotalPrice(), new BigDecimal("100"));
        price = AmountUtil.scale(price, 0);
        map.put("total_fee", price.intValue() + "");

        if(StringUtils.isEmpty(order2WeiXinOrderRequestVo.getOpenId())){
            map.put("trade_type", "APP");
        }else{
//            map.put("trade_type", "JSAPI");
            map.put("trade_type", "APP");//pengyu modify 20190704
            map.put("openid", order2WeiXinOrderRequestVo.getOpenId());
        }
        map.put("spbill_create_ip", order2WeiXinOrderRequestVo.getIp());
        map.put("notify_url", weixinPayCallbackURL);
        map.put("attach", appid);
        String result = WeiXinPayUtilBase.sign(map, weixinMchKey);
        map.put("sign", result);
        String xml = XmlUtil.map2Xml(map);
        log.info("xml:" + xml);
        String rsp = HttpUtils.postRequestXml(WeiXinPayUtilBase.WEIXIN_UNIFIEDORDER_URL, xml);
        log.info("微信统一下单返回:" + rsp);
        Map<String, Object> rpsmap = XmlUtil.Xml2Map(rsp);
        order2WeiXinOrderResponseVo.setReturnCode(rpsmap.get("return_code").toString());
        order2WeiXinOrderResponseVo.setMsg(rpsmap.get("return_msg").toString());
        // 请求错误
        if (!SUCCESS.equals(order2WeiXinOrderResponseVo.getReturnCode())) {
            return order2WeiXinOrderResponseVo;
        }
        if (WeiXinPayUtilBase.verify(rpsmap, weixinMchKey)) {
            // 业务逻辑错误
            if (!SUCCESS.equals(rpsmap.get("result_code").toString())) {
                order2WeiXinOrderResponseVo.setReturnCode(rpsmap.get("result_code").toString());
                order2WeiXinOrderResponseVo.setMsg(rpsmap.get("err_code_des").toString());
                return order2WeiXinOrderResponseVo;
            }
            map.clear();
            //公众号
//            map.put("appId", weixinAppid);
//            map.put("timeStamp", System.currentTimeMillis() / 1000);
//            map.put("nonceStr",
//                    new StringBuilder(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());
//            map.put("package", "prepay_id=" + rpsmap.get("prepay_id").toString());
//            map.put("signType", "MD5");
             map.put("appid", weixinAppid);
            map.put("partnerid", WeiXinPayUtilBase.getweiXinPropertieBykey(appid + "Weixin.mchId"));
            map.put("prepayid",  rpsmap.get("prepay_id").toString());
            map.put("package", "Sign=WXPay");
            map.put("noncestr",
                    new StringBuilder(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());
            map.put("timestamp", System.currentTimeMillis() / 1000);

//////////////////
            result = WeiXinPayUtilBase.sign(map, weixinMchKey);
            map.put("paySign", result);
              xml = XmlUtil.map2Xml(map);
            log.info("xml:" + xml);
            order2WeiXinOrderResponseVo.setAppId(map.get("appid").toString());
            order2WeiXinOrderResponseVo.setPartnerid(map.get("partnerid").toString());
            order2WeiXinOrderResponseVo.setPrepayid(map.get("prepayid").toString());
            order2WeiXinOrderResponseVo.setTimeStamp(map.get("timestamp").toString());
            order2WeiXinOrderResponseVo.setNonceStr(map.get("noncestr").toString());
            order2WeiXinOrderResponseVo.setPackageStr(map.get("package").toString());
//            order2WeiXinOrderResponseVo.setSignType(map.get("signType").toString());
            order2WeiXinOrderResponseVo.setPaySign(map.get("paySign").toString());
        } else {
            // 返回签名不匹配
            order2WeiXinOrderResponseVo.setMsg("返回签名不匹配");
        }
        return order2WeiXinOrderResponseVo;
    }

    /**
     * 查询微信订单状态
     *
     * @param weixinAppid
     * @param mch_id
     * @param weixinMchKey
     * @param orderNo
     * @throws UnsupportedEncodingException
     */
    public void queryWeiXinOrder(String weixinAppid, String mch_id, String weixinMchKey, String orderNo) throws UnsupportedEncodingException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("appid", weixinAppid);
        map.put("mch_id", mch_id);
        map.put("out_trade_no", orderNo);
        map.put("nonce_str",
                new StringBuilder(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());
        String result = WeiXinPayUtilBase.sign(map, weixinMchKey);
        map.put("sign", result);
        String xml = XmlUtil.map2Xml(map);
        System.out.println(xml);
        String rsp = HttpUtils.postRequestXml("https://api.mch.weixin.qq.com/pay/orderquery", xml);
        System.out.println(rsp);
    }

    public void modifyOrderDisplay(OrderInfo info) throws BusinessException {
        OrderInfo orderInfo = OrderInfo.getById(info.getOrderNo());
        if (orderInfo == null) {
            throw new BusinessException("订单" + info.getOrderNo() + "不存在");
        }
        if (orderInfo.getStatus() != OrderStatus.payedDone.value()
                && orderInfo.getStatus() != OrderStatus.canceledDone.value()
                && orderInfo.getStatus() != OrderStatus.overdueDone.value()) {
            throw new BusinessException("订单进行中不能修改订单隐藏状态");
        }
        if (info.getHide() != 0 && info.getHide() != 1) {
            throw new BusinessException("订单 隐藏状态修改,传值错误:" + info.getHide());
        }
        orderInfo.setHide(info.getHide());
        orderInfo.updateOrderHide();
    }

    /**
     * 修改订单附加消息
     *
     * @param info
     * @throws BusinessException
     */
    public void modifyOrderAttach(OrderInfo info) throws BusinessException {
        OrderInfo orderInfo = OrderInfo.getById(info.getOrderNo());
        if (orderInfo == null) {
            throw new BusinessException("订单" + info.getOrderNo() + "不存在");
        }
        orderInfo.setAttach(info.getAttach());
        orderInfo.updateOrderAttach();
    }

    /**
     * 批量支付
     */
    public void orderAlreadyPaid() throws Exception {
        // ali支付工具
        AliPayUtil aliPayUtil = SysApplicationContextAware.getApplication().getBean("aliPayUtil", AliPayUtil.class);
        // 要发送的参数
        Map<String, String> paramMap = new HashMap<>();
        String batchNum = "1";
        // 签名
        String sign = null;
        paramMap.put("service", "batch_trans_notify");
        paramMap.put("partner", aliPayUtil.PARTNER);
        paramMap.put("_input_charset", AliPayUtil.INPUT_CHARSET);
        paramMap.put("sign_type", AliPayUtil.SIGN_TYPE);
//				付款账号名
        paramMap.put("account_name", "豪特");
        paramMap.put("detail_data", "");
        paramMap.put("batch_num", batchNum);
//				付款总金额
        paramMap.put("batch_fee", "20");
        paramMap.put("email", aliPayUtil.SELLER_EMAIL);
        paramMap.put("pay_date", generaterefundDate());
        try {
            sign = AliPayUtil.sign(paramMap);
        } catch (UnsupportedEncodingException e) {
            throw new BusinessException("当前支付宝退款业务，加密参数失败" + e.getMessage());
        }
        paramMap.put("sign", sign);
//				LOGGER.info("支付宝退款的发送参数:"+paramMap);
        // 发送退款业务
        String retStr = AliPayUtil.sendRefundRequest(paramMap);
        if (retStr == null || retStr.trim().length() == 0) {
            throw new BusinessException("当前支付宝退款业务，调用ali接口执行失败");
        }
        Map<String, Object> retMap = null;
        try {
            retMap = XmlUtil.Xml2Map(retStr);
        } catch (DocumentException e) {
            throw new BusinessException("当前支付宝退款业务，解析返回参数失败" + e.getMessage());
        }
        String retResult = (String) retMap.get("is_success");
    }

    /**
     * 退款的时间电
     *
     * @return
     */
    private String generaterefundDate() {
        return UUIDUtil.getCurrentDate(null, "yyyyMMdd");
    }

//    public static void main(String[] args) {
//        // ali支付工具
//// 要发送的参数
//        Map<String, String> paramMap = new HashMap<>();
//        String batchNum = "1";
//        // 签名
//        String sign = null;
//
////	alipay.partner=2088721134926061
////			#卖家支付宝账号
////			alipay.sellerEmail =3267800170@qq.com
////			#卖家用户ID，卖家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字
////			alipay.sellerUserId 2088721134926061
//        paramMap.put("service", "batch_trans_notify");
//        paramMap.put("partner", "2088721134926061");
//        paramMap.put("_input_charset", AliPayUtil.INPUT_CHARSET);
//        paramMap.put("sign_type", AliPayUtil.SIGN_TYPE);
//        paramMap.put("notify_url", "http://171.212.112.209:18080/orderService/weixinPayCallback");
////	付款账号名
//        paramMap.put("account_name", "四川豪特新能有限公司");
//        System.out.println("四川豪特新能有限公司");
////	格式为：流水号1^收款方账号1^收款账号姓名1^付款金额1^备注说明1|流水号2^收款方账号2^收款账号姓名2^付款金额2^备注说明2。
//        paramMap.put("detail_data", "123^18010511232^倪波^0.01^批量测试");
//        paramMap.put("batch_no", "20180221123");
//        paramMap.put("batch_num", batchNum);
////	付款总金额
//        paramMap.put("batch_fee", "0.01");
//        paramMap.put("email", "3267800170@qq.com");
//        paramMap.put("pay_date", "20180221");
//        try {
//            sign = AliPayUtil.sign(paramMap);
//        } catch (UnsupportedEncodingException e) {
//            System.out.println("当前支付宝退款业务，加密参数失败" + e.getMessage());
//        }
//        paramMap.put("sign", sign);
////	paramMap.put("sign", "HkcK7Edvy8Fwl4ZPfAMjx2oIE9HQ367BSubMwHU/DB0kKX8SU6tkK8JlvF5bc9noGSWKjEk0xuqEwJef882xXBuqQ84MJRNOtzX0536HuRI6AxzBEGNAHqQbyXZiCj8wweguOZ7ePAPRSGQGL/lT85Nk7IY2l8pswzM1YUPHZy8=");
//        // 发送退款业务
//        String retStr = AliPayUtil.sendRefundRequest(paramMap);
//        System.out.println(retStr);
//        if (retStr == null || retStr.trim().length() == 0) {
//            System.out.println("当前支付宝退款业务，调用ali接口执行失败");
//        }
////	Map<String, Object> retMap = null;
////	try {
////		retMap = XmlUtil.Xml2Map(retStr);
////	} catch (DocumentException e) {
////		System.out.println("当前支付宝退款业务，解析返回参数失败" + e.getMessage());
////	}
////	String retResult = (String) retMap.get("is_success");
////	System.out.println(retResult);
//    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("appid", "wxb8971fd2fa4647cc");
//        map.put("mch_id", "1532639811");
//        // 随机数
//        map.put("nonce_str",
//                new StringBuilder(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());
//
//        map.put("body", "1231");
//        map.put("out_trade_no", "0104201906061612362878");
//        // 计量单位为分 并且无小数
////    BigDecimal price = AmountUtil.multiply(dzOrder.getCaculatedTotalPrice(), new BigDecimal("100"));
////    price = AmountUtil.scale(price, 0);
//        map.put("total_fee", "11");
//        map.put("trade_type", "APP");
////    map.put("openid", order2WeiXinOrderRequestVo.getOpenId());
//        map.put("spbill_create_ip", "222.209.88.63");
//        map.put("notify_url", "http://www.jtxny.online:8093/orderService/weixinPayCallback");
//        map.put("attach", "124");
//        String result = WeiXinPayUtilBase.sign(map, "CF741C7D138B240D4490AD1328A1BB25");
//        map.put("sign", result);
//        String xml = XmlUtil.map2Xml(map);
//        log.info("xml:" + xml);
//        String rsp = HttpUtils.postRequestXml(WeiXinPayUtilBase.WEIXIN_UNIFIEDORDER_URL, xml);
//        log.info("微信统一下单返回:" + rsp);
        map.put("appId", "wxb8971fd2fa4647");
        map.put("partnerid", "1532639811");
        map.put("prepayid",  "wx051515455139011d08266e201976379600");
        map.put("package", "Sign=WXPay");
        map.put("nonceStr",
                new StringBuilder(UUIDUtil.getCurrentDate14(null)).append(UUIDUtil.randomNum(4)).toString());
        map.put("timeStamp", System.currentTimeMillis() / 1000);

//////////////////
      String  result = WeiXinPayUtilBase.sign(map, "CF741C7D138B240D4490AD1328A1BB25");
        map.put("paySign", result);
        String xml = XmlUtil.map2Xml(map);
        System.out.println(xml);
//        order2WeiXinOrderResponseVo.setAppId(map.get("appId").toString());
//        order2WeiXinOrderResponseVo.setPartnerid(map.get("partnerid").toString());
//        order2WeiXinOrderResponseVo.setPrepayid(map.get("prepayid").toString());
//        order2WeiXinOrderResponseVo.setTimeStamp(map.get("timeStamp").toString());
//        order2WeiXinOrderResponseVo.setNonceStr(map.get("nonceStr").toString());
//        order2WeiXinOrderResponseVo.setPackageStr(map.get("package").toString());
//        order2WeiXinOrderResponseVo.setSignType(map.get("signType").toString());
//        order2WeiXinOrderResponseVo.setPaySign(map.get("paySign").toString());
    }
}
